//
//  LCMusicPlayer.m
//  LCAudioPlay
//
//  Created by admin on 2017/9/24.
//  Copyright © 2017年 LC. All rights reserved.
//

#import "LCMusicPlayer.h"
#import "JKSongsMessStatus.h"
#import "NetworkTool+LCAVPlay.h"
#import "LCHistoryDataManager.h"

@interface LCMusicPlayer ()

@property (nonatomic ,strong) AVPlayerItem *playerItem;

//设置锁屏信息
@property (strong, nonatomic) NSMutableDictionary *songInfo;

@property (assign, nonatomic) BOOL playEnabled;

@property (strong, nonatomic) id loadingObserver;

@end


@implementation LCMusicPlayer{
    id _playerTimeObserver;
}
IMPLEMENTATION_SINGLETON(LCMusicPlayer)

- (instancetype)init
{
    self = [super init];
    if (self) {
        self.avPlayer = nil;
        _playerItem = nil;
        _playerTimeObserver = nil;
        _loadingObserver = nil;
        self.kstatus = LCMusicPlayerStatusPaused;
        self.listStatus = LCMusicListStatusAllCycle;
        _playEnabled = YES;//允许播放
    }
    return self;
}
#pragma mark - KVO
// 开始监视发生改变回调
- (void)startObserver {
    [self stopObserve];
    [self setupAVAudioBackgroundPlay];

    //播放完毕后     //给AVPlayerItem添加播放完成通知
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(audioPlayerDidFinishPlaying) name:AVPlayerItemDidPlayToEndTimeNotification   object:self.avPlayer.currentItem];
    for (NSInteger i = 0; i < 10; i++) {
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.1 * i * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
            self.currentTime = 0.000000;
            float total = CMTimeGetSeconds(self.avPlayer.currentItem.duration);
            if ([self.playingSong.duration containsString:@":"]) {
                NSArray *timeArr = [self.playingSong.duration componentsSeparatedByString:@":"];//:为分隔符;
                NSString *fen = timeArr[0];
                total = [fen floatValue] * 60;
                NSString *miao = timeArr[1];
                total = total + [miao floatValue];
            }
            self.totalTime = total;
            [[NSNotificationCenter defaultCenter] postNotificationName:LCMusicPlayerCurrentTimeDidChangedNotification
                                                                object:self
                                                              userInfo:@{
                                                                         kCurrentTime:@(0.000000),
                                                                         kTotalTime:@(total)
                                                                         }];
        });
    }
#pragma mark -  监听播放进度发送播放进度  -
    __weak typeof(self) weakSelf = self;
    self.kstatus = LCMusicPlayerStatusLoading;
    _loadingObserver = [self.avPlayer addPeriodicTimeObserverForInterval:CMTimeMake(1, 100) queue:dispatch_get_main_queue() usingBlock:^(CMTime time) {
        float current = CMTimeGetSeconds(time);
        if (weakSelf.kstatus == LCMusicPlayerStatusLoading) {
            if (current > 0.1) {
                weakSelf.kstatus = LCMusicPlayerStatusPlaying;
                [weakSelf setupAVAudioBackgroundPlay];
            }else{
                [[NSNotificationCenter defaultCenter] postNotificationName:LCMusicPlayerStatusDidChangedNotification object:weakSelf userInfo:@{kMusicPlayerStatus:@(weakSelf.kstatus)}];
            }
        }
    }];
        //对于1分钟以内 就每1秒刷新一次页面
    _playerTimeObserver = [self.avPlayer addPeriodicTimeObserverForInterval:CMTimeMake(1, 1) queue:dispatch_get_main_queue() usingBlock:^(CMTime time) {
        float current = CMTimeGetSeconds(time);
        float total = CMTimeGetSeconds(weakSelf.avPlayer.currentItem.duration);
        if (current) {
//            NSLog(@"当前%f, 总%f",current, total);
            weakSelf.currentTime = current;
            weakSelf.totalTime = total;
//            weakSelf.playProgress= current / total;
            
            //锁屏进度
            [weakSelf.songInfo setObject:[NSNumber numberWithFloat:current] forKey:MPNowPlayingInfoPropertyElapsedPlaybackTime];//当前时间
            [weakSelf.songInfo setObject:[NSNumber numberWithFloat:total] forKey:MPMediaItemPropertyPlaybackDuration];//总时间
            [[MPNowPlayingInfoCenter defaultCenter] setNowPlayingInfo:weakSelf.songInfo];

            if (current == total) {
                return ;
            }
            [[NSNotificationCenter defaultCenter] postNotificationName:LCMusicPlayerCurrentTimeDidChangedNotification
                                                                object:weakSelf
                                                              userInfo:@{
                                                                         kCurrentTime:@(weakSelf.currentTime),
                                                                         kTotalTime:@(weakSelf.totalTime)
                                                                         }];
        }
    }];
    
    //监控播放状态属性，
    [self addObserver:self forKeyPath:@"kstatus" options:NSKeyValueObservingOptionNew context:nil];
    
    // 监视播放歌曲的索引发生变化
    [self addObserver:self forKeyPath:@"selectedIndex" options:NSKeyValueObservingOptionNew context:nil];
    //注意AVPlayer也有一个status属性，通过监控它的status也可以获得播放状态
    [self.avPlayer.currentItem addObserver:self forKeyPath:@"status" options:NSKeyValueObservingOptionNew context:nil];
    //监听网络
    [self.avPlayer.currentItem addObserver:self forKeyPath:@"loadedTimeRanges" options:NSKeyValueObservingOptionNew context:nil];
}
// 结束监视发生改变回调
- (void)stopObserve {
    if(_loadingObserver != nil) {
        [self.avPlayer removeTimeObserver:_loadingObserver];
        _loadingObserver = nil;
    }

    if(_playerTimeObserver != nil) {
        [_LCPlayer.avPlayer removeTimeObserver:_playerTimeObserver];
        _playerTimeObserver = nil;
    }
    
    //移除 在控制台拖动进度条调节进度 观察者
    MPRemoteCommandCenter *commandCenter = [MPRemoteCommandCenter sharedCommandCenter];
    [commandCenter.togglePlayPauseCommand removeTarget:self];
    [commandCenter.nextTrackCommand removeTarget:self];
    [commandCenter.previousTrackCommand removeTarget:self];

    [commandCenter.changePlaybackPositionCommand removeTarget:self];
}

///初始化播放 初始化avplayerItem、avplayer
- (void)setupPlayerWithSong:(JKSongsMessStatus *)song
{
    if (![[kNetworkTool mp3WithUrl:song.fileUrl] isEqualToString:song.fileUrl]) {
        song.filePath = [kNetworkTool mp3WithUrl:song.fileUrl];
    }
    //下载好的,播放本地磁盘
    if ([kNetworkTool isFileExist:song.filePath urlStr:song.fileUrl]){
        if (self.kstatus == LCMusicPlayerStatusCut) {
            [self stop];            //切歌播放
            self.avPlayer = [[AVPlayer alloc] initWithURL:[NSURL fileURLWithPath:song.filePath]];
            self.playerItem = self.avPlayer.currentItem;
            [self startObserver];
        }else{
            if (self.avPlayer == nil) {
                self.avPlayer = [[AVPlayer alloc] initWithURL:[NSURL fileURLWithPath:song.filePath]];
                self.playerItem = self.avPlayer.currentItem;
                [self startObserver];
            }
        }
    }else{
        //csrl
//        song.fileUrl = @"http://v.jxvdy.com/sendfile/w5bgP3A8JgiQQo5l0hvoNGE2H16WbN09X-ONHPq3P3C1BISgf7C-qVs6_c8oaw3zKScO78I--b0BGFBRxlpw13sf2e54QA";
    
        //网络播放
        self.playerItem = [AVPlayerItem playerItemWithURL:[kNetworkTool configPlayerWithURL:song.fileUrl]];
        if (self.kstatus == LCMusicPlayerStatusCut) {
            [self stop];//            切歌播放 , 需要先将以前的清空
            self.avPlayer = [AVPlayer playerWithPlayerItem:self.playerItem];
            [self startObserver];
            
        }else{
            if (self.avPlayer == nil) {//最开始的列表初始化播放
                //判断是否存在, 否就重新播放, 是就不执行
                self.avPlayer = [AVPlayer playerWithPlayerItem:self.playerItem];
                [self startObserver];
            }
        }
    }

    //暂停播放以及其他
    [self.avPlayer play];
    
    if (self.kstatus == LCMusicPlayerStatusPaused) {
        self.kstatus = LCMusicPlayerStatusPlaying;
    }
}

#pragma mark - 属性 -
// 当前播放歌曲对象
- (JKSongsMessStatus *)playingSong {
    if(self.songs == nil || self.selectedIndex >= self.songs.count) {
        return nil;
    }
    return [self.songs objectAtIndex:self.selectedIndex];
}

-(void)setCurrentTime:(float)currentTime{
    _currentTime = currentTime;
}

#pragma mark - 控制 -
// 通过歌曲索引播放歌曲
- (void)playAtIndex:(NSInteger)index isSelectPlay:(BOOL)isSelectIndexPlay{


    // 判断歌曲列表是否为空
    if(self.songs == nil || self.songs.count == 0) {
        [[NSOperationQueue mainQueue] addOperationWithBlock:^{
           [SVProgressHUD showInfoWithStatus:@"歌曲列表为空!"];
        }];
        if (self.kstatus == LCMusicPlayerStatusCut) {
            self.kstatus = LCMusicPlayerStatusPlaying;
        }
        return;
    }
    [LCFloatingWindow sharedInstance].playSlider.value = 0;//重置播放条的进度
    if (!isSelectIndexPlay) {//区别是否列表选择好的歌曲播放
        if(self.listStatus == LCMusicListStatusSingleCycle){//"单曲循环"
            index = self.selectedIndex;
        }else if(self.listStatus == LCMusicListStatusRandom){//"随机播放"
            index = arc4random_uniform((int)_songs.count);
            if (index == self.selectedIndex) {
                index++;
            }
        }
    }else{
        self.kstatus = LCMusicPlayerStatusCut;
    }
    
    // 处理如果是点击上一曲的情况,如果上一曲已经到达第一首,就让他回到最后一首歌曲
    if(index < 0) {
        index = self.songs.count - 1;
    }
    
    // 处理如果是点击最后一曲的情况,如果最后一曲已经是最后一曲,就让它回到第一首歌曲
    if(index >= self.songs.count) {
        index = 0;
    }
    // 获取歌曲对象
    JKSongsMessStatus *song = self.songs[index];
    @try {
        [self setupLockScreenAtSong:song];
    } @catch (NSException *exception) { }
    [self setupPlayerWithSong:song];

    [self createRemoteCommandCenter];//添加锁屏拖动和耳机监听
    self.selectedIndex = index;

    self.selectedJKSongsMessStatus = song;
    if ([_LCPlayer.playingSong.singerName isEqualToString:@"圣经新约"] || [_LCPlayer.playingSong.singerName isEqualToString:@"圣经旧约"]) {
        _LCPlayer.playingShengJing = 1;
        NSDictionary *json = [song yy_modelToJSONObject];
        
        [[NSUserDefaults standardUserDefaults] setObject:json.copy forKey:@"BIBLETEXT"];

    }else{//非圣经,普通歌曲纪录
        _LCPlayer.playingShengJing = 0;
        NSDictionary *json = [song yy_modelToJSONObject];
        
        for (NSInteger i = 0; i < self.selectedData.count; i++) {
            NSDictionary *dict = self.selectedData[i];
            if ([json[@"title"] isEqualToString:dict[@"title"]]) {
                [self.selectedData removeObject:dict];
            }
        }
//        NSLog(@"self.selectedData = %@", self.selectedData);

        [self.selectedData addObject:json];
        [[NSUserDefaults standardUserDefaults] setObject:self.selectedData.copy forKey:@"TENSONGS"];
    }
    
}
-(NSMutableArray *)downloadData{
    if (_downloadData == nil) {
        _downloadData = [NSMutableArray array];
        if ([[NSUserDefaults standardUserDefaults] objectForKey:@"DOWNLOADONGS"] != nil) {
            [_downloadData addObjectsFromArray:[[NSUserDefaults standardUserDefaults] objectForKey:@"DOWNLOADONGS"]];
        }
//        NSLog(@"_downloadData = %@", _downloadData);
    }
    return _downloadData;
}

-(NSMutableArray *)selectedData{
    if (_selectedData == nil) {
        _selectedData = [NSMutableArray array];
        if ([[NSUserDefaults standardUserDefaults] objectForKey:@"TENSONGS"] != nil) {
            [_selectedData addObjectsFromArray:[[NSUserDefaults standardUserDefaults] objectForKey:@"TENSONGS"]];
        }
//        NSLog(@"_selectedData = %@", _selectedData);
    }
    if (_selectedData.count > 10) {
        [_selectedData removeObjectAtIndex:0];
    }
    return _selectedData;
}
-(NSMutableArray *)selectedVideoData{
    if (_selectedVideoData == nil) {
        _selectedVideoData = [NSMutableArray array];
        if ([[NSUserDefaults standardUserDefaults] objectForKey:@"TENVIDEOS"] != nil) {
            [_selectedVideoData addObjectsFromArray:[[NSUserDefaults standardUserDefaults] objectForKey:@"TENVIDEOS"]];
        }
//        NSLog(@"_selectedVideoData = %@", _selectedVideoData);
    }
    if (_selectedVideoData.count > 10) {
        [_selectedVideoData removeObjectAtIndex:0];
    }
    return _selectedVideoData;
}

-(void)setupLockScreenAtSong:(JKSongsMessStatus *)song{
    
    //设置锁屏info
    NSMutableDictionary *songInfo = [ [NSMutableDictionary alloc] init];
    _songInfo = songInfo;
    if ([song.title isEqualToString:@""]||song.title.length == 0 ||[song.title isEqualToString:@"(null)"]||song.title == nil || [song.title isKindOfClass:[NSNull class]] ) {
    }
    else{
        //锁屏标题
        [songInfo setObject:song.title forKey:MPMediaItemPropertyTitle];//标题
    }
    if ([song.singerName isEqualToString:@""]||song.singerName.length == 0 ||[song.singerName isEqualToString:@"(null)"]||song.singerName == nil || [song.singerName isKindOfClass:[NSNull class]]  ) {
    }else{
        [songInfo setObject:song.singerName forKey:MPMediaItemPropertyAlbumTitle];//专辑名称
    }
    //锁屏图片
    UIImageView *imageView = [[UIImageView alloc] init];

    [imageView sd_setImageWithURL:[NSURL URLWithString:song.image] placeholderImage:[UIImage imageNamed:@"placeholder"] completed:^(UIImage * _Nullable image, NSError * _Nullable error, SDImageCacheType cacheType, NSURL * _Nullable imageURL) {
        if (imageView.image) {
            MPMediaItemArtwork *albumArt = [[MPMediaItemArtwork alloc] initWithImage:imageView.image];
            [songInfo setObject: albumArt forKey:MPMediaItemPropertyArtwork ];
            [[MPNowPlayingInfoCenter defaultCenter] setNowPlayingInfo:songInfo ];//刷新
            
        }
    }];
}
//锁屏界面开启和监控远程控制事件
- (void)createRemoteCommandCenter{
    /*lyricsAnalysis*/
    //远程控制命令中心 iOS 7.1 之后  详情看官方文档：https://developer.apple.com/documentation/mediaplayer/mpremotecommandcenter

    MPRemoteCommandCenter *commandCenter = [MPRemoteCommandCenter sharedCommandCenter];
    
    //    commandCenter.togglePlayPauseCommand 耳机线控的暂停/播放
    [commandCenter.togglePlayPauseCommand addTargetWithHandler:^MPRemoteCommandHandlerStatus(MPRemoteCommandEvent * _Nonnull event) {
        NSLog(@"耳机线控的暂停/播放");
        return MPRemoteCommandHandlerStatusSuccess;
    }];
    
    [commandCenter.pauseCommand addTargetWithHandler:^MPRemoteCommandHandlerStatus(MPRemoteCommandEvent * _Nonnull event) {
        if(self.comeFrome != 1 ){
            [self pause];
        }
        return MPRemoteCommandHandlerStatusSuccess;
    }];
    [commandCenter.playCommand addTargetWithHandler:^MPRemoteCommandHandlerStatus(MPRemoteCommandEvent * _Nonnull event) {
        
        if(self.comeFrome != 1 ){
            [self play];
        }
 
        return MPRemoteCommandHandlerStatusSuccess;
    }];
    
    [commandCenter.previousTrackCommand addTargetWithHandler:^MPRemoteCommandHandlerStatus(MPRemoteCommandEvent * _Nonnull event) {
        NSLog(@"上一首");
        [self prev];
        return MPRemoteCommandHandlerStatusSuccess;
    }];

    [commandCenter.nextTrackCommand addTargetWithHandler:^MPRemoteCommandHandlerStatus(MPRemoteCommandEvent * _Nonnull event) {
        NSLog(@"下一首");
        [self next];
        return MPRemoteCommandHandlerStatusSuccess;
    }];
    
    //在控制台拖动进度条调节进度（仿QQ音乐的效果）
    [commandCenter.changePlaybackPositionCommand addTargetWithHandler:^MPRemoteCommandHandlerStatus(MPRemoteCommandEvent * _Nonnull event) {
        CMTime totlaTime = self.avPlayer.currentItem.duration;
        MPChangePlaybackPositionCommandEvent * playbackPositionEvent = (MPChangePlaybackPositionCommandEvent *)event;
//        float sliderValue = slider.value * CMTimeGetSeconds(_LCPlayer.avPlayer.currentItem.duration);//* _LCPlayer.totalTime;
//        [self.avPlayer seekToTime:CMTimeMake(sliderValue, 1)];
        @try {
            [self.avPlayer seekToTime:CMTimeMake(totlaTime.value*playbackPositionEvent.positionTime/CMTimeGetSeconds(totlaTime), totlaTime.timescale)];
        } @catch (NSException *exception) {
            NSLog(@"exception = %@", exception);
        } @finally {
            
        }
        return MPRemoteCommandHandlerStatusSuccess;
    }];
    
    
}

// 播放音乐
- (void)play{
    [self playAtIndex:self.selectedIndex isSelectPlay:NO];
}

// 暂停音乐
- (void)pause{
    if (self.avPlayer != nil) {
        [self.avPlayer pause];
        self.kstatus = LCMusicPlayerStatusPaused;
    }
}
- (void)stop{
    if (self.avPlayer == nil) return;
    [self pause];
    [self removeObserver];
    self.avPlayer = nil;
}

- (void)removeObserver {
    
    AVPlayerItem * songItem = self.avPlayer.currentItem;
    if(_loadingObserver) {
        [self.avPlayer removeTimeObserver:_loadingObserver];
        _loadingObserver = nil;
    }
    if (_playerTimeObserver) {
        [self.avPlayer removeTimeObserver:_playerTimeObserver];
        _playerTimeObserver = nil;
    }
    @try {//防止多次重复删除
        [self removeObserver:self forKeyPath:@"kstatus"];
        [self removeObserver:self forKeyPath:@"selectedIndex"];
        [songItem removeObserver:self forKeyPath:@"status"];
        [songItem removeObserver:self forKeyPath:@"loadedTimeRanges"];
    } @catch (NSException *exception) {}

    [self.avPlayer replaceCurrentItemWithPlayerItem:nil];
    
    [[NSNotificationCenter defaultCenter] removeObserver:self];
    
}

// 下一曲
- (void)next{
    if (_playEnabled){
        self.kstatus = LCMusicPlayerStatusCut;
        [self playAtIndex:self.selectedIndex + 1 isSelectPlay:NO];
    }
    [self noQuickClick];
}

// 上一曲
- (void)prev{
    if (_playEnabled){
        self.kstatus = LCMusicPlayerStatusCut;
        [self playAtIndex:self.selectedIndex - 1 isSelectPlay:NO];
    }
    [self noQuickClick];
}
//屏蔽快速点击 和重置播放条的进度
- (void)noQuickClick {
    _playEnabled = NO;
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.8 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        _playEnabled = YES;
    });
}

- (void)dealloc
{
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}

/**
 *  通过KVO监控播放器状态
 *
 *  @param keyPath 监控属性
 *  @param object  监视器
 *  @param change  状态改变
 *  @param context 上下文
 */
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *,id> *)change context:(void *)context {
    
    AVPlayerItem * songItem = object;
    __weak typeof(self) weakSelf = self;

    if ([keyPath isEqualToString:@"kstatus"]) {
        [[NSNotificationCenter defaultCenter] postNotificationName:LCMusicPlayerStatusDidChangedNotification object:weakSelf userInfo:@{kMusicPlayerStatus:@(weakSelf.kstatus)}];
    }
    else if ([keyPath isEqualToString:@"status"]) {
        switch (weakSelf.avPlayer.status) {
            case AVPlayerStatusReadyToPlay:
//                NSLog(@"KVO：准备完毕");
                break;
            default:
                break;
        }
    }
    else if([keyPath isEqualToString:@"selectedIndex"]) {
        [[NSNotificationCenter defaultCenter] postNotificationName:LCMusicPlayerPlayingSongDidChangedNotification object:weakSelf userInfo:@{kMusicPlayerPlayingSong:weakSelf.playingSong}];
//        NSLog(@"索引发生变化");
//        NSLog(@"self.playingSong.title = %@", weakSelf.playingSong.title);
    }
    if ([keyPath isEqualToString:@"loadedTimeRanges"]) {
        NSTimeInterval timeInterval = [self availableDuration];// 计算缓冲进度
        CMTime duration = songItem.duration;
        CGFloat totalDuration = CMTimeGetSeconds(duration);
        self.bufferProgress = timeInterval / totalDuration;

        [[NSNotificationCenter defaultCenter] postNotificationName:LCBufferProgressDidChangedNotification
                                                            object:weakSelf
                                                          userInfo:@{
                                                                     kBufferProgress:@(timeInterval / totalDuration)
                                                                     }];

    }
}
- (NSTimeInterval)availableDuration {
    NSArray *loadedTimeRanges = [[self.avPlayer currentItem] loadedTimeRanges];
    CMTimeRange timeRange = [loadedTimeRanges.firstObject CMTimeRangeValue];// 获取缓冲区域
    float startSeconds = CMTimeGetSeconds(timeRange.start);
    float durationSeconds = CMTimeGetSeconds(timeRange.duration);
    NSTimeInterval result = startSeconds + durationSeconds;// 计算缓冲总进度
    return result;
}


- (void)audioPlayerDidFinishPlaying{
    [self next];
    
}
-(void)downloadSong{
    @try {
        JKSongsMessStatus *song = self.songs[self.selectedIndex];
        [kNetworkTool downloadSongWithUrl:song];//下载歌曲文件
    } @catch (NSException *exception) {
        NSLog(@"exception = %@", exception);
    } @finally {
        
    }

}

- (void)setupAVAudioBackgroundPlay {
    //设置静音也播放 后台播放
    AVAudioSession *session = [AVAudioSession sharedInstance];
    [session setCategory:AVAudioSessionCategorySoloAmbient error:nil];//软件启动 把别的音乐停止掉
    [session setCategory:AVAudioSessionCategoryPlayback error:nil];
    [session setActive:YES error:nil];
}

@end
